<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="referrer" content="never" />
    <title>FLIP demo</title>
    <style>
      * {
        margin: 0;
        box-sizing: border-box;
        padding: 0;
      }

      body {
        max-width: 500px;
        margin: auto;
      }

      .loading {
        margin: 12px;
        text-align: center;
      }

      .action {
        margin: 12px;
        text-align: center;
      }

      .action button {
        margin-right: 8px;
      }

      .link {
        display: block;
        padding: 8px;
        text-align: center;
        color: red;
      }

      .wrap {
        display: flex;
        flex-wrap: wrap;
        column-count: 4;
      }

      .img-wrap {
        width: 25%;
        padding: 8px;
      }

      .img {
        width: 100%;
        height: 200px;
        border-radius: 8px;
        object-fit: cover;
      }

      .move {
        transition: transform 1s;
      }

      [v-cloak] {
        display: none;
      }
    </style>
  </head>
  <body>
    <div id="app" v-cloak>
      <div class="action">
        <button @click="add">
          <span v-show="adding">下载中……</span>
          <span v-show="!adding">追加图片</span>
        </button>
        <button @click="shuffle">乱序图片</button>
        <button @click="reset">重置</button>
      </div>
      <div v-if="loading" class="loading">正在加载图片……</div>
      <div v-else class="wrap">
        <div class="img-wrap" v-for="src in imgs" :key="src">
          <img ref="imgs" class="img" :src="src" />
        </div>
      </div>
    </div>
    <script src="./web-animation-polyfill.js"></script>
    <script src="./vue.js"></script>
    <script src="./util.js"></script>
    <script src="./mock.js"></script>
    <script>
      let initialGetSister = getSisterGenerator()
      new Vue({
        el: "#app",
        data() {
          return {
            adding: false,
            loading: false,
            getSister: initialGetSister,
            imgs: [],
            imgHeights: [],
            imgsLoaded: false,
            leftImgIndexes: [],
            rightImgIndexes: [],
          }
        },
        async created() {
          this.loading = true
          const imgs = this.getSister()
          await preload(imgs)
          this.imgs = imgs
          this.loading = false
        },
        methods: {
          async add() {
            if (this.adding) {
              return
            }

            this.adding = true
            const newData = this.getSister()
            await preload(newData)
            this.adding = false

            this.scheduleAnimation(() => {
              this.imgs = newData.concat(this.imgs)
            })
          },
          shuffle() {
            this.scheduleAnimation(() => {
              this.imgs = shuffle(this.imgs)
            })
          },
          scheduleAnimation(update) {
            // 获取旧图片的位置
            const prevImgs = this.$refs.imgs.slice()
            const prevSrcRectMap = createSrcRectMap(prevImgs)
            // 更新数据
            update()
            // DOM更新后
            this.$nextTick(() => {
              const currentSrcRectMap = createSrcRectMap(prevImgs)
              Object.keys(prevSrcRectMap).forEach((src) => {
                const currentRect = currentSrcRectMap[src]
                const prevRect = prevSrcRectMap[src]

                const invert = {
                  left: prevRect.left - currentRect.left,
                  top: prevRect.top - currentRect.top,
                }

                const keyframes = [
                  {
                    transform: `translate(${invert.left}px, ${invert.top}px)`,
                  },
                  { transform: "translate(0, 0)" },
                ]
                const options = {
                  duration: 300,
                  easing: "cubic-bezier(0,0,0.32,1)",
                }

                const animation = currentRect.img.animate(keyframes, options)
              })
            })
          },
          reset() {
            this.getSister = getSisterGenerator()
            this.imgs = this.getSister()
          },
        },
      })

      function createSrcRectMap(imgs) {
        return imgs.reduce((prev, img) => {
          const rect = img.getBoundingClientRect()
          const { left, top } = rect
          prev[img.src] = { left, top, img }
          return prev
        }, {})
      }
    </script>
  </body>
</html>
